﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace cubeworld.GUI
{
    public class Textbox
    {
        #region fields

        bool _visible = true;
        bool _enabled = true;
        String _text = String.Empty;
        Vector2 _location = Vector2.Zero;
        bool _focused = false;
        SpriteFont _font;
        int _maxChars = 40;

        Texture2D _dummyTexture;

        Color _borderColor = Color.Black;
        Color _activeForeColor = Color.Black;
        Color _inactiveForeColor = Color.DarkGray;
        Color _activeBackColor = Color.White;
        Color _inactiveBackColor = Color.LightGray;

        int _borderWidth = 1;
        bool _hasBorder = true;
        KeyboardState _currentKeyboardState;
        int _cursorPosition = 0;

        #endregion

        #region properties

        public string Text
        {
            get { return _text; }
        }

        public Vector2 Location
        {
            get { return _location; }
            set { _location = value; }
        }

        public bool Focused
        {
            get { return _focused; }
        }

        public Color BorderColor
        {
            get { return _borderColor; }
            set { _borderColor = value; }
        }

        public Color ActiveForeColor
        {
            get { return _activeForeColor; }
            set { _activeForeColor = value; }
        }

        public Color InactiveForeColor
        {
            get { return _inactiveForeColor; }
            set { _inactiveForeColor = value; }
        }

        public Color ActiveBackColor
        {
            get { return _activeBackColor; }
            set { _activeBackColor = value; }
        }

        public Color InactiveBackColor
        {
            get { return _inactiveBackColor; }
            set { _inactiveBackColor = value; }
        }

        public int BorderWidth
        {
            get { return _borderWidth; }
            set { _borderWidth = value; }
        }

        public bool HasBorder
        {
            get { return _hasBorder; }
            set { _hasBorder = value; }
        }

        public SpriteFont Font
        {
            get { return _font; }
            set { _font = value; }
        }

        public Rectangle Bounds
        {
            get
            {
                int x = (int)Location.X;
                int y = (int)Location.Y;
                int width = (int)(_font.MeasureString(" ").X * _maxChars);
                int height = (int)(_font.MeasureString(" ").Y);

                return new Rectangle(x,y,width,height);
            }
        }

        #endregion

        #region methods

        public Textbox(Vector2 location, int maxChars, SpriteFont font)
        {
            _location = location;
            _maxChars = maxChars;
            _font = font;
            _dummyTexture = new Texture2D(Data.graphicsDevice, 1, 1);
            _dummyTexture.SetData(new[] {Color.White});
        }

        public void Draw(SpriteBatch batch)
        {
            if (!_visible)
                return;

            DrawBackground(batch);
            DrawBorder(batch);
            DrawText(batch);
        }

        void DrawText(SpriteBatch batch)
        {
            batch.DrawString(Font, Text.Length > _maxChars ? Text.Substring(_text.Length - _maxChars+1) : Text, new Vector2(Location.X + 3 + BorderWidth, Location.Y), Focused ? ActiveForeColor : InactiveForeColor);
        }

        void DrawBorder(SpriteBatch batch)
        {
            batch.Draw(_dummyTexture, new Rectangle(Bounds.X, Bounds.Y, Bounds.Width, BorderWidth), BorderColor);
            batch.Draw(_dummyTexture, new Rectangle(Bounds.X, Bounds.Y, BorderWidth, Bounds.Height), BorderColor);
            batch.Draw(_dummyTexture, new Rectangle(Bounds.X + Bounds.Width - BorderWidth, Bounds.Y, BorderWidth, Bounds.Height), BorderColor);
            batch.Draw(_dummyTexture, new Rectangle(Bounds.X, Bounds.Y + Bounds.Height - BorderWidth, Bounds.Width, BorderWidth), BorderColor);
        }

        void DrawBackground(SpriteBatch batch)
        {
            batch.Draw(_dummyTexture, Bounds, _focused ? ActiveBackColor : InactiveBackColor);
        }

        public void Update()
        {
            if (!_enabled)
                return;

            Rectangle mouseRectangle = new Rectangle(Mouse.GetState().X, Mouse.GetState().Y, 1, 1);

            if (Mouse.GetState().LeftButton == ButtonState.Pressed)
            {
                if (Bounds.Intersects(mouseRectangle))
                {
                    _focused = true;
                }
                else
                {
                    _focused = false;
                }
            }

            if (Focused)
            {
                String newChar = "";
                KeyboardState previousKeyboardState = _currentKeyboardState;
                _currentKeyboardState = Keyboard.GetState();

                if (previousKeyboardState.IsKeyDown(Keys.Back) &&
                    _currentKeyboardState.IsKeyUp(Keys.Back))
                {
                    if (_text.Length > 0)
                    {
                        _text = _text.Remove(_text.Length - 1, 1);
                        _cursorPosition--;
                    }
                }
                else if (previousKeyboardState.IsKeyDown(Keys.Space) &&
                         _currentKeyboardState.IsKeyUp(Keys.Space))
                {
                    _text += " ";
                    _cursorPosition++;
                }
                else
                {
                    newChar = CheckPressedKey(previousKeyboardState);

                    if (_currentKeyboardState.IsKeyDown(Keys.LeftShift) ||
                        _currentKeyboardState.IsKeyDown(Keys.RightShift))
                    {
                        newChar = newChar.ToUpper();
                    }

                    if (previousKeyboardState.GetPressedKeys().Length > 0)
                    {
                        _text += newChar;
                        if (newChar != "")
                            _cursorPosition++;
                    }
                }
            }
        }

        #region helpermethods
        private string CheckPressedKey(KeyboardState previousKeyboardState)
        {
            string newChar = "";

            if (_currentKeyboardState.IsKeyUp(Keys.A) &&
                previousKeyboardState.IsKeyDown(Keys.A))
            {
                newChar = "a";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.B) &&
                previousKeyboardState.IsKeyDown(Keys.B))
            {
                newChar = "b";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.C) &&
                previousKeyboardState.IsKeyDown(Keys.C))
            {
                newChar = "c";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.D) &&
                previousKeyboardState.IsKeyDown(Keys.D))
            {
                newChar = "d";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.E) &&
                previousKeyboardState.IsKeyDown(Keys.E))
            {
                newChar = "e";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.F) &&
                previousKeyboardState.IsKeyDown(Keys.F))
            {
                newChar = "f";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.G) &&
                previousKeyboardState.IsKeyDown(Keys.G))
            {
                newChar = "g";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.H) &&
                previousKeyboardState.IsKeyDown(Keys.H))
            {
                newChar = "h";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.I) &&
                previousKeyboardState.IsKeyDown(Keys.I))
            {
                newChar = "i";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.J) &&
                previousKeyboardState.IsKeyDown(Keys.J))
            {
                newChar = "j";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.K) &&
                previousKeyboardState.IsKeyDown(Keys.K))
            {
                newChar = "k";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.L) &&
                previousKeyboardState.IsKeyDown(Keys.L))
            {
                newChar = "l";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.M) &&
                previousKeyboardState.IsKeyDown(Keys.M))
            {
                newChar = "m";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.N) &&
                previousKeyboardState.IsKeyDown(Keys.N))
            {
                newChar = "n";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.O) &&
                previousKeyboardState.IsKeyDown(Keys.O))
            {
                newChar = "o";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.P) &&
                previousKeyboardState.IsKeyDown(Keys.P))
            {
                newChar = "p";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.Q) &&
                previousKeyboardState.IsKeyDown(Keys.Q))
            {
                newChar = "q";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.R) &&
                previousKeyboardState.IsKeyDown(Keys.R))
            {
                newChar = "r";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.S) &&
                previousKeyboardState.IsKeyDown(Keys.S))
            {
                newChar = "s";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.T) &&
                previousKeyboardState.IsKeyDown(Keys.T))
            {
                newChar = "t";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.U) &&
                previousKeyboardState.IsKeyDown(Keys.U))
            {
                newChar = "u";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.V) &&
                previousKeyboardState.IsKeyDown(Keys.V))
            {
                newChar = "v";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.W) &&
                previousKeyboardState.IsKeyDown(Keys.W))
            {
                newChar = "w";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.X) &&
                previousKeyboardState.IsKeyDown(Keys.X))
            {
                newChar = "x";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.Y) &&
                previousKeyboardState.IsKeyDown(Keys.Y))
            {
                newChar = "y";
            }

            if (_currentKeyboardState.IsKeyUp(Keys.Z) &&
                previousKeyboardState.IsKeyDown(Keys.Z))
            {
                newChar = "z";
            }

            return newChar;
        }


        #endregion
        #endregion
    }
}